#include "RX8010.h"
u8 dec2bcd(u8 dec)
{
    return ((dec / 10 * 16) + (dec % 10));
}

u8 bcd2dec(u8 bcd)
{
    return ((bcd / 16 * 10) + (bcd % 16));
}
void getDateTime(struct DateTime *ti)
{
    //	u8 i;
    //	dateTime dt;
    u8 temp[7];
    I2C_ReadNbyte(RX8010_ADDR, 0x10, temp, 7);
    ti->second = bcd2dec(temp[0]);
    ti->minute = bcd2dec(temp[1]);
    ti->hour = bcd2dec(temp[2]);
    ti->week = bcd2dec(temp[3]);
    ti->date = bcd2dec(temp[4]);
    ti->month = bcd2dec(temp[5]);
    ti->year = bcd2dec(temp[6]);
}
void setTime(struct DateTime *ti)
{
    u8 i;
    u8 temp[7];
    temp[0] = ti->second;
    temp[1] = ti->minute;
    temp[2] = ti->hour;
    temp[3] = ti->week;
    temp[4] = ti->date;
    temp[5] = ti->month;
    temp[6] = ti->year;
    for (i = 0; i < 7; i++)
        temp[i] = dec2bcd(temp[i]);
    I2C_WriteNbyte(RX8010_ADDR, 0x10, temp, 7);
}
byte readFromModule(byte address)
{
    u8 read;
    I2C_ReadNbyte(RX8010_ADDR, address, &read, 1);
    return read;
}
byte setBinary(byte binary, byte pos, byte flagVal)
{
    if (flagVal == 1)
    {
        return binary | (1 << pos);
    }

    return binary & (~(1 << pos));
}
void writeToModule(byte address, byte wtiteData)
{
    I2C_WriteNbyte(RX8010_ADDR, address, &wtiteData, 1);
}
void writeFlag(byte address, byte pos, byte value)
{
    byte addressValue = readFromModule(address);
    addressValue = setBinary(addressValue, pos, value);
    writeToModule(address, addressValue);
}
void disableFCT()
{
    writeFlag(RX8010_EXT, RX8010_TE_POS, 0);
    writeFlag(RX8010_CTRL, RX8010_TSTP_POS, 1);
}
void setFCT(byte pin, uint16_t multiplier, byte frequency)
{
    u8 firstHalf, secondHalf;
    if (pin > 1)
    {
        writeFlag(RX8010_CTRL, RX8010_TIE_POS, 0);
    }
    else
    {
        writeFlag(RX8010_IRQ, RX8010_TMPIN_POS, pin);
        writeFlag(RX8010_CTRL, RX8010_TIE_POS, 1);
    }
    firstHalf = multiplier & 0xff;
    secondHalf = multiplier >> 8;

    writeToModule(RX8010_TCOUNT0, firstHalf);
    writeToModule(RX8010_TCOUNT1, secondHalf);

    writeFlag(RX8010_EXT, RX8010_TSEL0_POS, getValueFromBinary(frequency, RX8010_TSEL0_POS));
    writeFlag(RX8010_EXT, RX8010_TSEL1_POS, getValueFromBinary(frequency, RX8010_TSEL1_POS));
    writeFlag(RX8010_EXT, RX8010_TSEL2_POS, getValueFromBinary(frequency, RX8010_TSEL2_POS));
    // enable FCT
    writeFlag(RX8010_CTRL, RX8010_TSTP_POS, 0);
    writeFlag(RX8010_CTRL, RX8010_TIE_POS, 1);
    writeFlag(RX8010_EXT, RX8010_TE_POS, 1);
}
/* void setFCTOutput(byte pin)
{
    if (pin > 1)
    {
        writeFlag(RX8010_CTRL, RX8010_TIE_POS, 0);
    }
    else
    {
        writeFlag(RX8010_IRQ, RX8010_TMPIN_POS, pin);
        writeFlag(RX8010_CTRL, RX8010_TIE_POS, 1);
    }
}
void setFCTCounter(uint16_t multiplier, byte frequency)
{
    byte firstHalf = multiplier & 0b11111111;
    byte secondHalf = multiplier >> 8;

    writeToModule(RX8010_TCOUNT0, firstHalf);
    writeToModule(RX8010_TCOUNT1, secondHalf);

    writeFlag(RX8010_EXT, RX8010_TSEL0_POS, getValueFromBinary(frequency, RX8010_TSEL0_POS));
    writeFlag(RX8010_EXT, RX8010_TSEL1_POS, getValueFromBinary(frequency, RX8010_TSEL1_POS));
    writeFlag(RX8010_EXT, RX8010_TSEL2_POS, getValueFromBinary(frequency, RX8010_TSEL2_POS));
} */
byte getValueFromBinary(byte binary, byte pos)
{
    return ((binary >> pos) & 1) == 1 ? 1 : 0;
}
/*void enableFCT()
{
    writeFlag(RX8010_CTRL, RX8010_TSTP_POS, 0);
    writeFlag(RX8010_CTRL, RX8010_TIE_POS, 1);
    writeFlag(RX8010_EXT, RX8010_TE_POS, 1);
}*/
void resetRX8010()
{
    writeToModule(RX8010_RESV17, RX8010_ADDR17_DEF_VAL);
    writeToModule(RX8010_RESV30, RX8010_ADDR30_DEF_VAL);
    writeToModule(RX8010_RESV31, RX8010_ADDR31_DEF_VAL);
    writeToModule(RX8010_IRQ, RX8010_IRQ_DEF_VAL);

    writeFlag(RX8010_EXT, RX8010_TE_POS, 0);
    writeFlag(RX8010_FLAG, RX8010_VLF_POS, 0);

    writeToModule(RX8010_CTRL, RX8010_CTRL_DEF_VAL);
}

void setFOUT(byte pin, byte frequency)
{
    switch (frequency)
    {
    case 3:
        writeFlag(RX8010_EXT, RX8010_FSEL0_POS, 1);
        writeFlag(RX8010_EXT, RX8010_FSEL1_POS, 1);
        break;
    case 2:
        writeFlag(RX8010_EXT, RX8010_FSEL0_POS, 0);
        writeFlag(RX8010_EXT, RX8010_FSEL1_POS, 1);
        break;
    case 1:
        writeFlag(RX8010_EXT, RX8010_FSEL0_POS, 1);
        writeFlag(RX8010_EXT, RX8010_FSEL1_POS, 0);
        break;
    case 0:
    default:
        disableFOUT();
        return;
    }

    writeFlag(RX8010_IRQ, RX8010_FOPIN0_POS, pin == 1 ? 1 : 0);
    writeFlag(RX8010_IRQ, RX8010_FOPIN1_POS, 0);
}

void disableFOUT()
{
    writeFlag(RX8010_EXT, RX8010_FSEL0_POS, 0);
    writeFlag(RX8010_EXT, RX8010_FSEL1_POS, 0);
}
void enableTUI()
{
    writeFlag(RX8010_CTRL, RX8010_UIE_POS, 1);
}

void disableTUI()
{
    writeFlag(RX8010_CTRL, RX8010_UIE_POS, 0);
}
void setTUIMode(BOOL minute)
{
    writeFlag(RX8010_EXT, RX8010_USEL_POS, minute ? 1 : 0);
    enableTUI();
}

BOOL checkTUI()
{
    byte flag = readFromModule(RX8010_FLAG);
    BOOL interrupted = getValueFromBinary(flag, RX8010_UF_POS) == 1;

    if (interrupted)
    {
        writeFlag(RX8010_FLAG, RX8010_UF_POS, 0);
    }

    return interrupted;
}
